struct Mtrl
{
	float4 ambient;
	float4 diffuse;
	float4 spec;
	float specPower;
};

struct DirLight
{
	float4 ambient;
	float4 diffuse;
	float4 spec;
	float3 dirW;
};

extern uniform matrix gWorldInvs;
extern uniform matrix gWVP;
extern uniform Mtrl gMtrl;
extern uniform DirLight gLight;
extern uniform float3 gEyePos;
extern uniform texture gColorTexture;
extern uniform texture gNormalTexture;

sampler ColorS = sampler_state
{
	Texture = <gColorTexture>;
	MinFilter = ANISOTROPIC;
	MaxAnisotropy = 8;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU  = WRAP;
    AddressV  = WRAP;
};

sampler NormalS = sampler_state
{
	Texture = <gNormalTexture>;
	MinFilter = ANISOTROPIC;
	MaxAnisotropy = 8;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU  = WRAP;
    AddressV  = WRAP;
};

struct OUTPUT_VS
{
	float4 posH : POSITION0;
	float3 toEyeT : TEXCOORD0;
	float3 lightDirT : TEXCOORD1;
	float2 tex : TEXCOORD2;
};

OUTPUT_VS NormalMapVS(float3 posL : POSITION0,
						float3 tangentL : TANGENT0,
						float3 binormalL : BINORMAL0,
						float3 normalL : NORMAL0,
						float2 tex : TEXCOORD0)
{
	OUTPUT_VS output = (OUTPUT_VS)0;
	output.posH = mul(float4(posL, 1.0f), gWVP);
	output.tex = tex;

	float3x3 TBN;
	TBN[0] = tangentL;
	TBN[1] = binormalL;
	TBN[2] = normalL;

	float3x3 localToTangent = transpose(TBN);

	float3 eyePosL = mul(float4(gEyePos, 1.0f), gWorldInvs).xyz;
	float3 toEyeL = eyePosL - posL;
	float3 toEyeT = mul(toEyeL, localToTangent);
	output.toEyeT = toEyeT;

	float3 lightDirL = mul(float4(gLight.dirW, 0.0f), gWorldInvs).xyz;
	float3 lightDirT = mul(lightDirL, localToTangent);
	output.lightDirT = lightDirT;

	return output;
}

float4 NormalMapPS(float3 toEyeT    : TEXCOORD0,
                   float3 lightDirT : TEXCOORD1,
                   float2 tex      : TEXCOORD2) : COLOR
{
	toEyeT    = normalize(toEyeT);
	lightDirT = normalize(lightDirT);
	
	float3 lightVecT = -lightDirT;

	float3 normalT = tex2D(NormalS, tex);
	
    normalT = 2.0f*normalT - 1.0f;

	normalT = normalize(normalT);
	
	float3 r = reflect(lightDirT, normalT);
	
	float t  = pow(max(dot(r, toEyeT), 0.0f), gMtrl.specPower);

	float s = max(dot(lightVecT, normalT), 0.0f);
	
	float3 spec = t*(gMtrl.spec*gLight.spec).rgb;
	float3 diffuse = s*(gMtrl.diffuse*gLight.diffuse).rgb;
	float3 ambient = gMtrl.ambient*gLight.ambient;
	
	float4 texColor = tex2D(ColorS, tex);

	float3 color = (ambient + diffuse)*texColor.rgb + spec;

    return float4(color, gMtrl.diffuse.a*texColor.a);
}

technique NormalMapTech
{
    pass P0
    {
        vertexShader = compile vs_2_0 NormalMapVS();
        pixelShader  = compile ps_2_0 NormalMapPS();
    }
}